package com.matchmealpha;

import jjil.android.RgbImageAndroid;
import jjil.core.RgbImage;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.Log;

public class FilterEffects {
	static double RWGT = 0.3086;
	static double GWGT = 0.6094;
	static double BWGT = 0.0820;
	public final static int COOL_SEPIA = 0;
	public static final int ROUNDED_EDGES = 1;

	public static Bitmap applyFilter(Bitmap image, int filter) {
		switch (filter) {
		case COOL_SEPIA:
			image = coolSepia(image);
			break;
		case ROUNDED_EDGES:
			image = getRoundedCornerBitmap(image);
		default:
			break;
		}
		return image;
	}

	public static Bitmap coolSepia(Bitmap image) {
		double mat[][] = { { 1, 0, 0, 0 }, { 0, 1, 0, 0 }, { 0, 0, 1, 0 },
				{ 0, 0, 0, 1 } };

		mat = sepia(mat);
		mat = contrast(1.2, mat);
		mat = saturate(.3, mat);
		image = linearOp(mat, image);
		image = getRoundedCornerBitmap(image);
		return image;
	}
	
	 public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {
		    Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
		        bitmap.getHeight(), Config.ARGB_8888);
		    Canvas canvas = new Canvas(output);
		 
		    final int color = 0xff424242;
		    final Paint paint = new Paint();
		    final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
		    final RectF rectF = new RectF(rect);
		    final float roundPx = 25;
		 
		    paint.setAntiAlias(true);
		    canvas.drawARGB(0, 0, 0, 0);
		    paint.setColor(color);
		    canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
		 
		    paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
		    canvas.drawBitmap(bitmap, rect, rect, paint);
		 
		    return output;
		  }


	public static double[][] contrast(double c, double[][] mat) {
		double[][] arr = { { c, 0, 0, 0 }, { 0, c, 0, 0 }, { 0, 0, c, 0 },
				{ 0, 0, 0, 1 } };

		return multiply(mat, arr);
	}

	public static double[][] sepia(double[][] mat) {

		double[][] arr = { { 0.85, 0.55, 0.06, 0 }, { 0.60, 0.35, 0.05, 0 },
				{ 0.60, 0.05, 0.04, 0 }, { 0, 0, 0, 1 } };

		return multiply(mat, arr);

	}

	public static double[][] saturate(double s, double[][] mat) {

		double[][] arr = {
				{ (1.0 - s) * RWGT + s, (1.0 - s) * RWGT, (1.0 - s) * RWGT, 0 },
				{ (1.0 - s) * GWGT, (1.0 - s) * GWGT + s, (1.0 - s) * GWGT, 0 },
				{ (1.0 - s) * BWGT, (1.0 - s) * BWGT, (1.0 - s) * BWGT + s, 0 },
				{ 0, 0, 0, 1 } };

		return multiply(mat, arr);
	}

	public Bitmap sepia2sep(Bitmap bit) {

		double[][] arr = { { 0.75, 0.45, 0.05, 0 }, { 0.50, 0.25, 0.04, 0 },
				{ 0.50, 0.04, 0.03, 0 }, { 0, 0, 0, 1 } };

		return linearOp(arr, bit);

	}

	public static Bitmap linearOp(double[][] mat, Bitmap bit) {
		RgbImage mRgbImage = RgbImageAndroid.toRgbImage(bit);
		int width = bit.getWidth();
		int height = bit.getHeight();
		int[] rgbData = mRgbImage.getData();
		int[] conv = new int[width * height];
		int sumR = 0;
		int sumG = 0;
		int sumB = 0;

		for (int x = 0; x < width; x++) {
			for (int y = 0; y < height; y++) {
				sumR = 0;
				sumG = 0;
				sumB = 0;

				int r = ((rgbData[y * width + x] >> 16) & 0xff);
				int g = ((rgbData[y * width + x] >> 8) & 0xff);
				int b = ((rgbData[y * width + x]) & 0xff);

				sumR = (int) (r * mat[0][0] + g * mat[1][0] + b * mat[2][0] + mat[3][0]);
				sumG = (int) (r * mat[0][1] + g * mat[1][1] + b * mat[2][1] + mat[3][1]);
				sumB = (int) (r * mat[0][2] + g * mat[1][2] + b * mat[2][2] + mat[3][2]);

				if (sumR > 255) {
					sumR = 255;
				}

				if (sumG > 255) {
					sumG = 255;
				}

				if (sumB > 255) {
					sumB = 255;
				}

				conv[y * width + x] = 0xff000000 | ((int) sumR << 16
						| (int) sumG << 8 | (int) sumB);
			}
		}
		System.arraycopy(conv, 0, rgbData, 0, width * height);
		bit = RgbImageAndroid.toBitmap(mRgbImage);
		return bit;

	}

	public Bitmap softedges(Bitmap bit) {

		RgbImage mRgbImage = RgbImageAndroid.toRgbImage(bit);
		int width = bit.getWidth();
		int height = bit.getHeight();
		int[] rgbData = mRgbImage.getData();
		int[] conv = new int[width * height];
		int sumR = 0;
		int sumG = 0;
		int sumB = 0;
		int edgeDis = (int) (.5 * width);

		for (int x = 0; x < width; x++) {
			for (int y = 0; y < height; y++) {
				sumR = 0;
				sumG = 0;
				sumB = 0;

				int R = ((rgbData[y * width + x] >> 16) & 0xff);
				int G = ((rgbData[y * width + x] >> 8) & 0xff);
				int B = ((rgbData[y * width + x]) & 0xff);

				double multi = ((double) x / (edgeDis)) + .2;

				if (x > width - edgeDis) {
					multi = (double) (width - x) / (edgeDis) + .2;
				}

				if (multi > 1) {
					multi = 1;
				}

				sumR = (int) (R * multi + G * 0 + B * 0);
				sumG = (int) (R * 0 + G * multi + B * 0);
				sumB = (int) (R * 0 + G * 0 + B * multi);

				if (sumR > 255) {
					sumR = 255;
				}

				if (sumG > 255) {
					sumG = 255;
				}

				if (sumB > 255) {
					sumB = 255;
				}

				conv[y * width + x] = 0xff000000 | ((int) sumR << 16
						| (int) sumG << 8 | (int) sumB);
			}
		}
		System.arraycopy(conv, 0, rgbData, 0, width * height);

		bit = RgbImageAndroid.toBitmap(mRgbImage);
		return bit;
	}

	public Bitmap grayscale(Bitmap bit) {

		RgbImage mRgbImage = RgbImageAndroid.toRgbImage(bit);
		int width = bit.getWidth();
		int height = bit.getHeight();
		int[] rgbData = mRgbImage.getData();
		int[] conv = new int[width * height];
		int sumR = 0;
		int sumG = 0;
		int sumB = 0;

		for (int x = 0; x < width; x++) {
			for (int y = 0; y < height; y++) {
				sumR = 0;
				sumG = 0;
				sumB = 0;

				int R = ((rgbData[y * width + x] >> 16) & 0xff);
				int G = ((rgbData[y * width + x] >> 8) & 0xff);
				int B = ((rgbData[y * width + x]) & 0xff);

				conv[y * width + x] = 0xff000000 | (((R + G + B) / 3) << 16)
						| (((R + G + B) / 3) << 8) | ((R + G + B) / 3);
			}
		}
		System.arraycopy(conv, 0, rgbData, 0, width * height);
		return RgbImageAndroid.toBitmap(mRgbImage);
	}

	public static double[][] multiply(double a[][], double b[][]) {
		// Remember RC, Row-Column.

		int aRows = a.length, aColumns = a[0].length, bRows = b.length, bColumns = b[0].length;

		double[][] resultant = new double[aRows][bColumns];

		for (int i = 0; i < aRows; i++) { // aRow
			for (int j = 0; j < bColumns; j++) { // bColumn
				for (int k = 0; k < aColumns; k++) { // aColumn
					resultant[i][j] += a[i][k] * b[k][j];
				}
			}
		}

		return resultant;
	}

	public static Bitmap combineImages(Bitmap image1, Bitmap image2) {
		// TODO Auto-generated method stub
		
		Bitmap combinedImage = combineImage(image1, image2);

		
		return combinedImage;
	}

	public static Bitmap combineImage(Bitmap image1, Bitmap image2) {

		Bitmap b = Bitmap.createBitmap((image1.getWidth() * 2) + 3, image1
				.getHeight(), Bitmap.Config.ARGB_8888);
		Canvas c = new Canvas(b);
		Paint p = new Paint();
		c.drawBitmap(image1, 0, 0, p);
		c.drawBitmap(image2, image1.getWidth() + 3, 0, p);

		return b;
	}

}
